/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

import marsnapi from 'libmarsnapi.so';
import connection from '@ohos.net.connection';
import ICallBack from './ICallBack';

class StnLogic {
  public static readonly TAG: string = "mars.StnLogic";

  /*static {
    Mars.loadDefaultMarsLibrary();
  }*/

  static Task = class {
    public static readonly ENORMAL: number = 0;
    public static readonly EFAST: number = 1;

    //priority
    public static readonly ETASK_PRIORITY_HIGHEST: number = 0;
    public static readonly ETASK_PRIORITY_0: number = 0;
    public static readonly ETASK_PRIORITY_1: number = 1;
    public static readonly ETASK_PRIORITY_2: number = 2;
    public static readonly ETASK_PRIORITY_3: number = 3;
    public static readonly ETASK_PRIORITY_NORMAL: number = 3;
    public static readonly ETASK_PRIORITY_4: number = 4;
    public static readonly ETASK_PRIORITY_5: number = 5;
    public static readonly ETASK_PRIORITY_LOWEST: number = 5;

    //channel selective
    public static readonly EShort: number = 0x1;
    public static readonly ELong: number = 0x2;
    public static readonly EBoth: number = 0x3;

    public constructor(channelselect?: number, cmdid?: number, cgi?: string, shortLinkHostList?: Array<string>) {
      if (channelselect == null && cmdid == null && shortLinkHostList == null) {
        this.taskID = StnLogic.genTaskID(); //ai.incrementAndGet();
        this.headers = new Map();
      } else {
        this.taskID = StnLogic.genTaskID(); //ai.incrementAndGet();
        this.channelSelect = channelselect;
        this.cmdID = cmdid;
        this.cgi = cgi;
        this.shortLinkHostList = shortLinkHostList;

        this.sendOnly = false;
        this.needAuthed = true;
        this.limitFlow = true;
        this.limitFrequency = true;

        this.channelStrategy = StnLogic.Task.ENORMAL;
        this.networkStatusSensitive = false;
        this.priority = StnLogic.Task.ETASK_PRIORITY_NORMAL;
        this.retryCount = -1;
        this.serverProcessCost = 0;
        this.totalTimeout = 0;
        this.userContext = null;
        this.headers = new Map();
        this.longPolling = false;
        this.longPollingTimeout = 0;
      }
    }

    public taskID: number;
    //unique task identify
    public channelSelect: number;
    //short,long or both
    public cmdID: number;
    public cgi: string;
    public shortLinkHostList: Array<string>;
    //host or ip

    //optional
    public sendOnly: boolean;
    public needAuthed: boolean;
    public limitFlow: boolean;
    public limitFrequency: boolean;
    public channelStrategy: number;
    //normal or fast
    public networkStatusSensitive: boolean;
    public priority: number;
    //@see priority
    public retryCount: number = -1;
    public serverProcessCost: number;
    //该TASK等待SVR处理的最长时间,也即预计的SVR处理耗时
    public totalTimeout: number;
    //total timeout, in ms
    public userContext: any;
    //user context
    public reportArg: string;
    public headers: Map<String, String>;
    public longPolling: boolean;
    public longPollingTimeout: number;
  }

  public static readonly INVALID_TASK_ID: number = -1;

  // STN callback errType
  public static readonly ectOK: number = 0;
  public static readonly ectFalse: number = 1;
  public static readonly ectDial: number = 2;
  public static readonly ectDns: number = 3;
  public static readonly ectSocket: number = 4;
  public static readonly ectHttp: number = 5;
  public static readonly ectNetMsgXP: number = 6;
  public static readonly ectEnDecode: number = 7;
  public static readonly ectServer: number = 8;
  public static readonly ectLocal: number = 9;

  //STN callback errCode
  public static readonly FIRSTPKGTIMEOUT: number = -500;
  public static readonly PKGPKGTIMEOUT: number = -501;
  public static readonly READWRITETIMEOUT: number = -502;
  public static readonly TASKTIMEOUT: number = -503;
  public static readonly SOCKETNETWORKCHANGE: number = -10086;
  public static readonly SOCKETMAKESOCKETPREPARED: number = -10087;
  public static readonly SOCKETWRITENWITHNONBLOCK: number = -10088;
  public static readonly SOCKETREADONCE: number = -10089;
  public static readonly SOCKETSHUTDOWN: number = -10090;
  public static readonly SOCKETRECVERR: number = -10091;
  public static readonly SOCKETSENDERR: number = -10092;
  public static readonly HTTPSPLITHTTPHEADANDBODY: number = -10194;
  public static readonly HTTPPARSESTATUSLINE: number = -10195;
  public static readonly NETMSGXPHANDLEBUFFERERR: number = -10504;
  public static readonly DNSMAKESOCKETPREPARED: number = -10606;

  //reportConnectStatus
  //status
  public static readonly NETWORK_UNKNOWN: number = -1;
  public static readonly NETWORK_UNAVAILABLE: number = 0;
  public static readonly GATEWAY_FAILED: number = 1;
  public static readonly SERVER_FAILED: number = 2;
  public static readonly CONNECTTING: number = 3;
  public static readonly CONNECTED: number = 4;
  public static readonly SERVER_DOWN: number = 5;

  //longlink identify check
  public static ECHECK_NOW: number = 0;
  public static ECHECK_NEXT: number = 1;
  public static ECHECK_NEVER: number = 2;

  //buf2Resp fail handle type
  public static RESP_FAIL_HANDLE_NORMAL: number = 0;
  public static RESP_FAIL_HANDLE_DEFAULT: number = -1;
  public static RESP_FAIL_HANDLE_SESSION_TIMEOUT: number = -13;
  public static RESP_FAIL_HANDLE_TASK_END: number = -14;
  public static TASK_END_SUCCESS: number = 0;

  private static callBack: StnLogic.ICallBack = null;

  private static reconnectCount: number = 0;


  static CgiProfile = class {
    public taskStartTime: number = 0;
    public startConnectTime: number = 0;
    public connectSuccessfulTime: number = 0;
    public startHandshakeTime: number = 0;
    public handshakeSuccessfulTime: number = 0;
    public startSendPacketTime: number = 0;
    public startReadPacketTime: number = 0;
    public readPacketFinishedTime: number = 0;
  }

  /**
   * 初始化网络层回调实例 App实现NetworkCallBack接口
   * @param _callBack native网络层调用java上层时的回调
   *
   */
  public static setCallBack(_callBack: StnLogic.ICallBack): void {
    StnLogic.callBack = _callBack;
  }

  /**
   * DEBUG IP 说明
   * setLonglinkSvrAddr,setShortlinkSvrAddr,setDebugIP 均可用于设置DEBUG IP
   * setLonglinkSvrAddr: 设置长链接的DEBUG IP;
   * setShortlinkSvrAddr: 设置短连接的DEBUG IP;
   * setDebugIP: 设置对应HOST(不区分长短链)的DEBUG IP;
   *
   * 优先级:
   * setDebugIP 为最高优先级
   * 同一个接口, 以最后设置的值为准
   */

  /**
   * @param host      长链接域名
   * @param ports     长链接端口列表
   * @param debugIP   长链接调试IP.如果有值,则忽略 host设置, 并使用该IP.
   */
  public static setLonglinkSvrAddr(host: string, ports: number[], debugIP?: string): number {
    console.info("StnLogic.setLonglinkSvrAddr(host:%s,ports:%o,debugIP:%s)",host,ports,debugIP);
    if (!debugIP) {
      debugIP = '';
    }
    let result = marsnapi.StnLogic_setLonglinkSvrAddr(host, ports, debugIP);
    return result
  }

  /**
   *
   * @param port      短链接(HTTP)端口
   * @param debugIP   短链接调试IP.如果有值,则所有TASK走短链接时,使用该IP代替TASK中的HOST
   */
  public static setShortlinkSvrAddr(port: number, debugIP?: string): number {
    console.info("StnLogic.setShortlinkSvrAddr(port:%d,debugIP:%s)",port,debugIP);
    let result
    if (debugIP == undefined) {
      result = marsnapi.StnLogic_setShortlinkSvrAddr(port, '');
    } else {
      result = marsnapi.StnLogic_setShortlinkSvrAddr(port, debugIP);
    }
    console.info("Mars: setShortlinkSvrAddr result " + result);
    return result
  }

  /**
   * 设置DEBUG IP
   * @param host  要设置的域名
   * @param ip    该域名对应的IP
   */
  public static setDebugIP(host: string, ip: string): number {
    console.info("StnLogic.setDebugIP(host:%s,ip:%s)",host,ip);
    let result = marsnapi.StnLogic_setDebugIP(host, ip);
    console.log("Mars: setDebugIP result " + result);
    return result
  }

  //async call
  public static startTask(task: StnLogic.Task): number {
    console.info("StnLogic.startTask task:" + JSON.stringify(task));
    let result = marsnapi.StnLogic_startTask(task);
    console.info("StnLogic.startTask task result " + JSON.stringify(result));
    return result
  }

  //sync call
  public static stopTask(taskID: number): number {
    console.info("StnLogic.stopTask(taskID:%d)",taskID);
    let result = marsnapi.StnLogic_stopTask(taskID);
    console.log("Mars: StnLogic_stopTask result " + result);
    return result
  }

  //sync call
  public static hasTask(taskID: number): boolean {
    console.info("StnLogic.hasTask(taskID:%d)",taskID);
    let value = marsnapi.StnLogic_hasTask(taskID);
    console.log("Mars: StnLogic.native_hasTask: " + value);
    return value == 0;
  }

  /**
   * 重做所有长短连任务. 注意这个接口会重连长链接.
   */
  public static redoTask(): number {
    let result = marsnapi.StnLogic_redoTask();
    console.log("Mars: native_redoTask result " + result);
    return result
  }

  /**
   * 停止并清除所有未完成任务.
   */
  public static clearTask(): number {
    let result = marsnapi.StnLogic_clearTask();
    console.log("Mars: native_clearTask result " + result);
    return result
  }

  /**
   * 停止并清除所有未完成任务并重新初始化
   */
  public static reset(): number {
    let result = marsnapi.StnLogic_reset();
    console.log("Mars: StnLogic_reset result " + result);
    return result
  }

  /**
   * 停止并清除所有未完成任务并重新初始化, 重新设置encoder version
   */
  public static resetAndInitEncoderVersion(packerEncoderVersion: number): number {
    console.info("StnLogic.resetAndInitEncoderVersion(packerEncoderVersion:%d)",packerEncoderVersion);
    let result = marsnapi.StnLogic_resetAndInitEncoderVersion(packerEncoderVersion);
    console.log("Mars: StnLogic_resetAndInitEncoderVersion result " + result);
    return result
  }

  /**
   * 设置备份IP,用于long/short svr均不可用的场景下
   * @param host  域名
   * @param ips   域名对应的IP列表
   */
  public static setBackupIPs(host: string, ips: string[]): number {
    console.info("StnLogic.setBackupIPs(host:%s,ips:%o)",host,ips);
    let result = marsnapi.StnLogic_setBackupIPs(host, ips);
    console.log("Mars: native_setBackupIPs result " + result);
    return result
  }

  /**
   * 检测长链接状态.如果没有连接上,则会尝试重连.
   */
  public static makesureLongLinkConnected(): number {
    let result = marsnapi.StnLogic_makesureLongLinkConnected();
    console.log("Mars: makesureLongLinkConnected result " + result);
    return result
  }

  /**
   * 信令保活
   * @param period 信令保活间隔,默认5S
   * @param keepTime 信令保活时间,默认20S
   */
  public static setSignallingStrategy(period: number, keepTime: number): number {
    console.info("StnLogic.setSignallingStrategy(period:%d,keepTime:%d)",period,keepTime);
    let result = marsnapi.StnLogic_setSignallingStrategy(period, keepTime);
    console.log("Mars: setSignallingStrategy result " + result);
    return result
  }

  /**
   * 发送一个信令保活包(如果有必要)
   */
  public static keepSignalling(): number {
    let result = marsnapi.StnLogic_keepSignalling();
    console.log("Mars: keepSignalling result " + result);
    return result
  }

  /**
   * 停止信令保活
   */
  public static stopSignalling(): number {
    let result = marsnapi.StnLogic_stopSignalling();
    console.log("Mars: stopSignalling result " + result);
    return result
  }

  /**
   * 设置客户端版本 放入长连私有协议头部
   * @param clientVersion
   */
  public static setClientVersion(clientVersion: number): number {
    console.info("StnLogic.setClientVersion(clientVersion:%d)",clientVersion);
    let result = marsnapi.StnLogic_setClientVersion(clientVersion);
    console.log("Mars: setClientVersion result " + result);
    return result
  }

  /**
   * 获取底层已加载模块
   * @return
   */
  public static getLoadLibraries(): Array<string> {
    let data = marsnapi.StnLogic_getLoadLibraries()
    console.info("Mars: StnLogic.native_getLoadLibraries: " + JSON.stringify(data))
    return data
  }

  public static genTaskID(): number {
    let result = marsnapi.StnLogic_genTaskID();
    console.info("Mars: StnLogic.native_genTaskID: " + result);
    return result;
  }

  /**
   *  要求上层进行AUTH操作.
   *  如果一个TASK要求AUTH状态而当前没有AUTH态,组件就会回调此方法
   */
  private static makesureAuthed(host: string): boolean {
    console.info("StnLogic.makesureAuthed(host:%s)",host);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return false;
      }
      return StnLogic.callBack.makesureAuthed(host);
    } catch (error) {
      console.info('Process Failed.makesureAuthed Cause: ' + error);
    }
    return false;
  }

  /**
   * 长连host设置到网络层 网络层向上层请求host dns结果
   * 短连task中设置host  网络层向上层请求host dns结果
   * @param host  域名
   * @return 空：底层实现解析
   */
  private static onNewDns(host: string): string[] {
    console.info("StnLogic.onNewDns(host:%s)",host);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return null;
      }
      return StnLogic.callBack.onNewDns(host);
    } catch (error) {
      console.info('Process Failed.onNewDns Cause: ' + error);
    }
    return null;
  }

  /**
   * 收到server push消息
   * @param cmdid     PUSH的CMDID,这个应该是APP跟SVR约定的值
   * @param data      PUSH下来的数据
   */
  private static onPush(channelID: string, cmdid: number, taskid: number, data: ArrayBuffer): void {
    console.info("StnLogic.onPush(channelID:%s,cmdid:%d,taskid:%d)",channelID,cmdid,taskid);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return;
      }
      StnLogic.callBack.onPush(cmdid, taskid, data);
    } catch (error) {
      console.info('Process Failed.onPush Cause: ' + error);
    }
  }

  /**
   * 网络层获取上层发送的数据内容
   * @param taskID
   * @param userContext
   * @param errCode 生成数据失败时的错误码
   * @return
   */
  public static req2Buf(taskID: number, userContext: any, channelSelect: number, host: string): object {
    console.info("StnLogic.req2Buf(taskID:%d,channelSelect:%d,host:%s)",taskID,channelSelect,host);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return [false, null, null];
      }
      let errCode: number[] = [0];
      let reqBuffer: ArrayBuffer = StnLogic.callBack.req2Buf(taskID, userContext, errCode, channelSelect, host);
      console.info("StnLogic.req2Buf call success, reqBuffer:" + new Uint8Array(reqBuffer));
      return [true, reqBuffer, errCode];
    } catch (error) {
      console.error('Process Failed.req2Buf Cause: ' + error);
    }
    return [false, null, null];
  }

  /**
   * 网络层将收到的信令回包交给上层解析
   * @param taskID
   * @param userContext
   * @param respBuffer 待解包的数据内容
   * @param errCode   解包错误码
   * @return
   */
  public static buf2Resp(taskID: number, userContext: any, respBuffer: ArrayBuffer, channelSelect: number): number {
    console.info("StnLogic.buf2Resp(taskID:%d,channelSelect:%d)",taskID,channelSelect);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return StnLogic.RESP_FAIL_HANDLE_TASK_END;
      }
      let errCode: number[] = [0];
      return StnLogic.callBack.buf2Resp(taskID, userContext, respBuffer, errCode, channelSelect);
    } catch (error) {
      console.error('Process Failed.buf2Resp Cause: ' + error);
    }
    return StnLogic.RESP_FAIL_HANDLE_TASK_END;
  }

  /**
   * 信令回包网络层处理完毕回调上层
   * @param taskID
   * @param userContext
   * @param errType 参见 ErrCmdType
   * @param errCode
   * @return
   */
  private static onTaskEnd(taskID: number, userContext: any, errType: number, errCode: number, profile: StnLogic.CgiProfile): number {
    console.info("StnLogic.onTaskEnd(taskID:%d,errType:%d,errCode:%d)",taskID,errType,errCode);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return 0;
      }
      return StnLogic.callBack.onTaskEnd(taskID, userContext, errType, errCode, profile);
    } catch (error) {
      console.error('Process Failed.onTaskEnd Cause: ' + error);
    }
    return 0;
  }

  /**
   * 上报信令消耗的流量
   * @param send
   * @param recv
   */
  public static trafficData(send: number, recv: number): void {
    console.info("StnLogic.trafficData(send:%d,recv:%d)",send,recv);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return;
      }
      StnLogic.callBack.trafficData(send, recv);
    } catch (error) {
      console.error('Process Failed.trafficData Cause: ' + error);
    }
  }

  /**
   * 网络层向上层反馈网络连接状态
   * @param status 综合状态，即长连+短连的状态
   *               kNetworkUnkown = -1, kNetworkUnavailable = 0, kGateWayFailed = 1, kServerFailed = 2, kConnecting = 3, kConnected = 4, kServerDown = 5
   * @param longlinkstatus  长连状态
   *                       kConnectIdle = 0, kConnecting = 1, kConnected, kDisConnected = 3, kConnectFailed = 4
   */
  private static reportConnectStatus(status: number, longlinkstatus: number): void {
    console.info("StnLogic.reportConnectStatus(status:%d,longlinkstatus:%d)",status,longlinkstatus);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return;
      }
      StnLogic.callBack.reportConnectInfo(status, longlinkstatus);
    } catch (error) {
      console.error('Process Failed.reportConnectStatus Cause: ' + error);
    }
  }

  /**
   * 长连信令校验
   * @param reqBuf        CLIENT的校验数据
   * @param reqBufHash    CLIENT校验数据的HASH值
   * @param cmdID         校验包的CMDID
   * @return ECHECK_NOW = 0, ECHECK_NEXT = 1, ECHECK_NEVER = 2
   */
  private static getLongLinkIdentifyCheckBuffer(channelID: string, reqBuf: ArrayBuffer, reqBufHash: ArrayBuffer, cmdID: number[]): number {
    console.info("StnLogic.getLongLinkIdentifyCheckBuffer(channelID:%s,cmdID:%o)",channelID,cmdID);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return StnLogic.ECHECK_NEVER;
      }
      return StnLogic.callBack.getLongLinkIdentifyCheckBuffer(reqBuf, reqBufHash, cmdID);
    } catch (error) {
      console.error('Process Failed.getLongLinkIdentifyCheckBuffer Cause: ' + error);
    }

    return StnLogic.ECHECK_NEVER;
  }

  /**
   * 长连信令校验回包
   * @param respBuf       SVR回复的校验应答数据
   * @param reqBufHash    对应的CLIENT校验数据HASH
   * @return true false
   */
  private static onLongLinkIdentifyResp(channelID: string, respBuf: number[], reqBufHash: number[]): boolean {
    console.info("StnLogic.onLongLinkIdentifyResp(channelID:%s)",channelID);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return false;
      }
      return StnLogic.callBack.onLongLinkIdentifyResp(respBuf, reqBufHash);
    } catch (error) {
      console.error('Process Failed.onLongLinkIdentifyResp Cause: ' + error);
    }

    return false;
  }

  private static requestNetCheckShortLinkHosts(): string[] {
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return null;
      }
      return StnLogic.callBack.requestNetCheckShortLinkHosts();
    } catch (error) {
      console.info('Process Failed.requestNetCheckShortLinkHosts Cause: ' + error);
    }

    return null;
  }

  private static requestDoSync(): void {
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return;
      }
      return StnLogic.callBack.requestDoSync();
    } catch (error) {
      console.info('Process Failed.requestDoSync Cause: ' + error);
    }
  }

  private static isLogoned(): boolean {
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return false;
      }
      return StnLogic.callBack.isLogoned();
    } catch (error) {
      console.info('Process Failed.isLogoned Cause: ' + error);
    }
    return false;
  }

  /**
   * Task运行完成时，STN将Task的运行时状态及统计数据返回给上层
   * @param taskString
   */
  private static reportTaskProfile(taskString: string): void {
    console.info("StnLogic.reportTaskProfile(taskString:%s)",taskString);
    try {
      if (StnLogic.callBack == null) {
        console.info('callback is null');
        return;
      }
      StnLogic.callBack.reportTaskProfile(taskString);
    } catch (error) {
      console.error('Process Failed.reportTaskProfile Cause: ' + error);
    }
  }

  public static reconnectStart(): number {
    let messageCallBack = () => {
      console.info("Mars: reconnectStart callback");
      connection.getDefaultNet().then((data: connection.NetHandle) => {
        console.info("Mars: reconnectStart makesureLongLinkConnected go: " + data.netId + " count " +
        StnLogic.reconnectCount);
        if (data.netId != 0) {
          if (StnLogic.reconnectCount < 3) {
            try {
              console.info("Mars: reconnectStart makesureLongLinkConnected connect");
              StnLogic.makesureLongLinkConnected();
              StnLogic.keepSignalling();
            } catch (e) {
              console.error("Mars: reconnectStart makesureLongLinkConnected e: " + e);
            }
          }
          StnLogic.reconnectCount++;
        } else {
          StnLogic.reconnectCount = 0;
        }
      });
    }
    let result = marsnapi.StnLogic_reconnectStart(messageCallBack);
    console.info("Mars: StnLogic_reconnectStart: " + result);
    return result;
  }


  public static reconnectStop(): number {
    let result = marsnapi.StnLogic_reconnectStop();
    console.info("Mars: StnLogic_reconnectStop: " + result);
    return result;
  }

  public static resetReconnect() {
    console.info("Mars: resetReconnect");
    StnLogic.reconnectCount = 0;
  }


  public static delayTask(callBack: ICallBack): number {
    let messageCallBack = () => {
      console.info("Mars: delayTask callback");
      if (callBack != null) {
        callBack.callBackResult();
      }
    }
    let result = marsnapi.StnLogic_delayTask(messageCallBack);
    console.info("Mars: StnLogic_delayTask: " + result);
    return result;
  }
}

namespace StnLogic {

  export type Task = typeof StnLogic.Task.prototype;

  export type CgiProfile = typeof StnLogic.CgiProfile.prototype;

  /**
   * 网络层调用java上层的接口类
   *
   * APP使用信令通道必须实现该接口
   * 接口用于信令通道处理完后回调上层
   */
  export interface ICallBack {

    /**
     * SDK要求上层做认证操作(可能新发起一个AUTH CGI)
     * @return
     */
    makesureAuthed(host: string): boolean;

    /**
     * SDK要求上层做域名解析.上层可以实现传统DNS解析,或者自己实现的域名/IP映射
     * @param host
     * @return
     */
    onNewDns(host: string): string[];

    /**
     * 收到SVR PUSH下来的消息
     * @param cmdid
     * @param data
     */
    onPush(cmdid: number, taskid: number, data: ArrayBuffer): void;

    /**
     * SDK要求上层对TASK组包
     * @param taskID    任务标识
     * @param userContext
     * @param reqBuffer 组包的BUFFER
     * @param errCode   组包的错误码
     * @return
     */
    req2Buf(taskID: number, userContext: any, errCode: number[], channelSelect: number, host: string): ArrayBuffer;

    /**
     * SDK要求上层对TASK解包
     * @param taskID        任务标识
     * @param userContext
     * @param respBuffer    要解包的BUFFER
     * @param errCode       解包的错误码
     * @return int
     */
    buf2Resp(taskID: number, userContext: any, respBuffer: ArrayBuffer, errCode: number[], channelSelect: number): number;

    /**
     * 任务结束回调
     * @param taskID            任务标识
     * @param userContext
     * @param errType           错误类型
     * @param errCode           错误码
     * @return
     */
    onTaskEnd(taskID: number, userContext: any, errType: number, errCode: number, profile: CgiProfile): number;

    /**
     * 流量统计
     * @param send
     * @param recv
     */
    trafficData(send: number, recv: number): void;

    /**
     * 连接状态通知
     * @param status    综合状态，即长连+短连的状态
     * @param longlinkstatus    仅长连的状态
     */
    reportConnectInfo(status: number, longlinkstatus: number): void;

    /**
     * SDK要求上层生成长链接数据校验包,在长链接连接上之后使用,用于验证SVR身份
     * @param identifyReqBuf    校验包数据内容
     * @param hashCodeBuffer    校验包的HASH
     * @param reqRespCmdID      数据校验的CMD ID
     * @return ECHECK_NOW(需要校验), ECHECK_NEVER(不校验), ECHECK_NEXT(下一次再询问)
     */
    getLongLinkIdentifyCheckBuffer(identifyReqBuf: ArrayBuffer, hashCodeBuffer: ArrayBuffer, reqRespCmdID: number[]): number;

    /**
     * SDK要求上层解连接校验回包.
     * @param buffer            SVR回复的连接校验包
     * @param hashCodeBuffer    CLIENT请求的连接校验包的HASH值
     * @return
     */
    onLongLinkIdentifyResp(buffer: number[], hashCodeBuffer: number[]): boolean;

    /**
     * 请求做sync
     */
    requestDoSync(): void;

    requestNetCheckShortLinkHosts(): string[];

    /**
     * 是否登录
     * @return true 登录 false 未登录
     */
    isLogoned(): boolean;

    reportTaskProfile(taskString: string): void;
  }
}

export default StnLogic;